// $Id: ustring.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#ifndef XPCOM_USTRING_HPP
#define XPCOM_USTRING_HPP

#include <xpcom/config.hpp>
#include <xpcom/string.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif

namespace xpcom {

//
// XPCOM UTF-8 string class
//
// Provides UTF-8 specific operations in addition to basic string operations.
// Also allows constructing and assigning from wstring.
//
// TODO Add UTF-8 specific functions
//
class XPCOM_DECL ustring : public string
{
    typedef ustring this_type;
    typedef string base_type;
public:
    //
    // Constructors and destructor
    //
    ustring();
    ustring(const ustring& s);
    ustring(const wstring& s);
    ustring(const string& s);
    ustring(const string& s, size_type pos, size_type n = npos);
    ustring(const value_type* s, size_type n = npos);
    ustring(size_type n, value_type c);

    template <typename InputIterator>
    ustring(InputIterator first, InputIterator last) :
        base_type(first, last)
    {
    }

    explicit ustring(const adopt_t& rhs) :
        base_type(rhs)
    {
    }

    explicit ustring(const depend_t& rhs) :
        base_type(rhs)
    {
    }

    template <size_type N>
    explicit ustring(const literal_t<N>& rhs) :
        base_type(rhs)
    {
    }

    ~ustring();

    //
    // Assignment
    //
    ustring& operator=(const ustring& s)
    {
        base_type::operator=(s);
        return *this;
    }

    ustring& operator=(const wstring& s)
    {
        return assign(s);
    }

    ustring& operator=(const string& s)
    {
        base_type::operator=(s);
        return *this;
    }

    ustring& operator=(const value_type* s)
    {
        base_type::operator=(s);
        return *this;
    }

    ustring& operator=(value_type c)
    {
        base_type::operator=(c);
        return *this;
    }

    ustring& assign(const wstring& s);

    ustring& assign(const string& s)
    {
        base_type::assign(s);
        return *this;
    }

    ustring& assign(const string& s, size_type pos, size_type n)
    {
        base_type::assign(s, pos, n);
        return *this;
    }

    ustring& assign(const value_type* s, size_type n = npos)
    {
        base_type::assign(s, n);
        return *this;
    }

    ustring& assign(size_type n, value_type c)
    {
        base_type::assign(n, c);
        return *this;
    }

    template <typename InputIterator>
    ustring& assign(InputIterator first, InputIterator last)
    {
        base_type::assign(first, last);
        return *this;
    }

    ustring& assign(const adopt_t& rhs)
    {
        base_type::assign(rhs);
        return *this;
    }

    ustring& assign(const depend_t& rhs)
    {
        base_type::assign(rhs);
        return *this;
    }

    template <size_type N>
    ustring& assign(const literal_t<N>& rhs)
    {
        base_type::assign(rhs);
        return *this;
    }

    //
    // Append
    //
    ustring& operator+=(const string& s)
    {
        base_type::operator+=(s);
        return *this;
    }

    ustring& operator+=(const value_type* s)
    {
        base_type::operator+=(s);
        return *this;
    }

    ustring& operator+=(value_type c)
    {
        base_type::operator+=(c);
        return *this;
    }

    ustring& append(const string& s)
    {
        base_type::append(s);
        return *this;
    }

    ustring& append(const string& s, size_type pos, size_type n)
    {
        base_type::append(s, pos, n);
        return *this;
    }

    ustring& append(const value_type* s, size_type n = npos)
    {
        base_type::append(s, n);
        return *this;
    }

    ustring& append(size_type n, value_type c)
    {
        base_type::append(n, c);
        return *this;
    }

    template <typename InputIterator>
    ustring& append(InputIterator first, InputIterator last)
    {
        base_type::append(first, last);
        return *this;
    }

    //
    // Insert
    //
    ustring& insert(size_type pos, const string& s)
    {
        base_type::insert(pos, s);
        return *this;
    }

    ustring& insert(
            size_type pos1, const string& s, size_type pos2, size_type n)
    {
        base_type::insert(pos1, s, pos2, n);
        return *this;
    }

    ustring& insert(size_type pos, const value_type* s, size_type n = npos)
    {
        base_type::insert(pos, s, n);
        return *this;
    }

    ustring& insert(size_type pos, size_type n, value_type c)
    {
        base_type::insert(pos, n, c);
        return *this;
    }

    void insert(iterator i, size_type n, value_type c)
    {
        base_type::insert(i, n, c);
    }

    template <typename InputIterator>
    void insert(iterator i, InputIterator first, InputIterator last)
    {
        base_type::insert(i, first, last);
    }

    iterator insert(iterator i, value_type c)
    {
        return base_type::insert(i, c);
    }

    //
    // Erase
    //
    iterator erase(iterator i1, iterator i2)
    {
        return base_type::erase(i1, i2);
    }

    iterator erase(iterator i)
    {
        return base_type::erase(i);
    }

    ustring& erase(size_type pos = 0, size_type n = npos)
    {
        base_type::erase(pos, n);
        return *this;
    }

    //
    // Replace
    //
    ustring& replace(size_type pos, size_type n, const string& s)
    {
        base_type::replace(pos, n, s);
        return *this;
    }

    ustring& replace(
            size_type pos1, size_type n1,
            const string& s, size_type pos2, size_type n2)
    {
        base_type::replace(pos1, n1, s, pos2, n2);
        return *this;
    }

    ustring& replace(
            size_type pos, size_type n1,
            const value_type* s, size_type n2 = npos)
    {
        base_type::replace(pos, n1, s, n2);
        return *this;
    }

    ustring& replace(size_type pos, size_type n1, size_type n2, value_type c)
    {
        base_type::replace(pos, n1, n2, c);
        return *this;
    }

    ustring& replace(iterator i1, iterator i2, const string& s)
    {
        base_type::replace(i1, i2, s);
        return *this;
    }

    ustring& replace(
            iterator i1, iterator i2, const value_type* s, size_type n = npos)
    {
        base_type::replace(i1, i2, s, n);
        return *this;
    }

    ustring& replace(iterator i1, iterator i2, size_type n, value_type c)
    {
        base_type::replace(i1, i2, n, c);
        return *this;
    }

    template <typename InputIterator>
    ustring& replace(
            iterator i1, iterator i2, InputIterator first, InputIterator last)
    {
        base_type::replace(i1, i2, first, last);
        return *this;
    }

    //
    // String operations
    //
    void swap(ustring& s)
    {
        base_type::swap(s);
    }

    ustring substr(size_type pos = 0, size_type n = npos) const;

    //
    // Conversion to UTF-16 string
    //
    void to_wstr(wstring& s) const;
    wstring wstr() const;
};

// operator +
inline ustring operator+(const ustring& lhs, const ustring& rhs)
{
    ustring str(lhs);
    str.append(rhs);
    return str;
}

inline ustring operator+(const ustring& lhs, const string& rhs)
{
    ustring str(lhs);
    str.append(rhs);
    return str;
}

inline ustring operator+(const string& lhs, const ustring& rhs)
{
    ustring str(lhs);
    str.append(rhs);
    return str;
}

inline ustring operator+(const ustring& lhs, const char* rhs)
{
    //XPCOM_ASSERT(rhs);
    ustring str(lhs);
    str.append(rhs);
    return str;
}

inline ustring operator+(const char* lhs, const ustring& rhs)
{
    //XPCOM_ASSERT(lhs);
    ustring str(lhs);
    str.append(rhs);
    return str;
}

inline ustring operator+(const ustring& lhs, char rhs)
{
    ustring str(lhs);
    str.append(ustring::size_type(1), rhs);
    return str;
}

inline ustring operator+(char lhs, const ustring& rhs)
{
    ustring str(ustring::size_type(1), lhs);
    str.append(rhs);
    return str;
}

// swap
inline void swap(ustring& lhs, ustring& rhs)
{
    lhs.swap(rhs);
}

// I/O
#ifndef XPCOM_NO_IOSTREAM
// TODO UTF-8 specific IO
#endif // XPCOM_NO_IOSTREAM

} // namespace xpcom

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif

#endif // XPCOM_USTRING_HPP
